using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;
using Rotempco.Core.ORM.Logic;
using System.Collections;

namespace Rotempco.Core.Web.Logic
{
    public class WebFormFillerLogicDEP
    {
        private static List<Type> GetControlTypes()
        {
            List<Type> controlTypes = new List<Type>();
            controlTypes.Add(typeof(TextBox));
            controlTypes.Add(typeof(Literal));
            controlTypes.Add(typeof(Label));
            controlTypes.Add(typeof(CheckBox));
            controlTypes.Add(typeof(RadioButton));
            controlTypes.Add(typeof(DropDownList));
            controlTypes.Add(typeof(Repeater));
            controlTypes.Add(typeof(HiddenField));
            controlTypes.Add(typeof(HyperLink));
            return controlTypes;
        }


        public static void FillForm<T>(T instance, Control container)
        {
            if (instance == null)
                return;

            List<Type> controlTypes = GetControlTypes();

            PropertyInfo[] properties = typeof(T).GetProperties();

            foreach (PropertyInfo propertyInfo in properties)
            {
                Control control = LocateControl(container, controlTypes, propertyInfo.Name);

                if (control == null || control.Parent is RepeaterItem)
                    continue;

                object propertyValue = propertyInfo.GetValue(instance, null);
                string textValue = propertyValue + "";

                if (control is DropDownList)
                {
                    if (!string.IsNullOrWhiteSpace(textValue) && long.Parse(textValue) > 0)
                        (control as DropDownList).SelectedValue = textValue;
                }
                else if (control is ITextControl)
                    (control as ITextControl).Text = textValue;
                else if (control is ICheckBoxControl)
                    (control as ICheckBoxControl).Checked = bool.Parse(textValue);
                else if (control is Repeater)
                {
                    List<object> propertyValueList = ConvertPropertyToObjectList(propertyValue);
                    FillRepeaterFromObjects(propertyValueList, (control as Repeater));
                }
                else if (control is HiddenField)
                    (control as HiddenField).Value = textValue;
                else if (control is HyperLink)
                    (control as HyperLink).Text = textValue;
            }
        }


        public static void FillObject<T>(T instance, Control container)
        {
            List<Type> controlTypes = GetControlTypes();

            PropertyInfo[] properties = typeof(T).GetProperties();

            foreach (PropertyInfo propertyInfo in properties)
            {
                Control control = LocateControl(container, controlTypes, propertyInfo.Name);

                if (control == null || control.Parent is RepeaterItem)
                    continue;

                object propertyValue = GetPropertyValueFromControl(control, propertyInfo);

                if (control is DropDownList)
                    FillObjectFromDropDownList<T>(instance, propertyInfo, propertyValue);
                else if (control is Repeater)
                    FillObjectsFromRepeater<T>(instance, propertyInfo, control as Repeater);
                else
                    propertyInfo.SetValue(instance, propertyValue, null);
            }
        }


        public static void FillRepeater<T>(List<T> items, Repeater repeater)
        {
            FillRepeaterFromObjects(items.Cast<object>().ToList(), repeater);
        }




        private static void FillRepeaterFromObjects(List<object> instanceList, Repeater repeater)
        {
            repeater.DataSource = instanceList;
            repeater.DataBind();

            if (instanceList.Count <= 0)
                return;

            List<Type> controlTypes = GetControlTypes();
            PropertyInfo[] properties = instanceList.First().GetType().GetProperties();

            int i = 0;

            foreach (RepeaterItem repeaterItem in repeater.Controls)
            {
                if (!(repeaterItem.ItemType == ListItemType.Item || repeaterItem.ItemType == ListItemType.AlternatingItem))
                    continue;

                object instance = instanceList[i++];

                foreach (PropertyInfo propertyInfo in properties)
                {
                    Control control = LocateControl(repeaterItem, controlTypes, propertyInfo.Name);

                    if (control == null)
                        continue;

                    object propertyValue = propertyInfo.GetValue(instance, null);
                    string textValue = propertyValue + "";

                    if (control is DropDownList)
                    {
                        object enumThingy = (int)propertyInfo.GetValue(instance, null);

                        (control as DropDownList).SelectedValue = enumThingy + "";
                    }
                    else if (control is ITextControl)
                        (control as ITextControl).Text = textValue;
                    else if (control is ICheckBoxControl)
                        (control as ICheckBoxControl).Checked = bool.Parse(textValue);
                    else if (control is Repeater)
                    {
                        List<object> propertyValueList = ConvertPropertyToObjectList(propertyValue);
                        FillRepeaterFromObjects(propertyValueList, (control as Repeater));
                    }
                    else if (control is HiddenField)
                        (control as HiddenField).Value = textValue;
                    else if (control is HyperLink)
                        (control as HyperLink).Text = textValue;
                }
            }
        }

        public static void FillObjects<T>(List<T> items, Repeater repeater)
        {
            FillObjectsFromRepeater(ConvertPropertyToObjectList(items), repeater);
        }

        private static void FillObjectsFromRepeater<T>(T instance, PropertyInfo propertyInfo, Repeater repeater)
        {
            object propertyValue = propertyInfo.GetValue(instance, null);
            List<object> propertyValueList = ConvertPropertyToObjectList(propertyValue);
            FillObjectsFromRepeater(propertyValueList, repeater);
        }

        private static void FillObjectsFromRepeater(List<object> items, Repeater repeater)
        {
            if (items.Count == 0)
                return;

            List<Type> controlTypes = GetControlTypes();
            PropertyInfo[] properties = items.First().GetType().GetProperties();

            int i = 0;

            foreach (RepeaterItem repeaterItem in repeater.Items)
            {
                object instance = items[i++];

                foreach (PropertyInfo propertyInfo in properties)
                {
                    Control control = LocateControl(repeaterItem, controlTypes, propertyInfo.Name);

                    if (control == null)
                        continue;

                    object value = GetPropertyValueFromControl(control, propertyInfo);
                    if (control is DropDownList)
                    {
                        if (propertyInfo.PropertyType == typeof(string))
                            propertyInfo.SetValue(instance, value + "", null);
                        else if (propertyInfo.PropertyType == typeof(int))
                            propertyInfo.SetValue(instance, int.Parse(value + ""), null);
                        else if (propertyInfo.PropertyType == typeof(double))
                            propertyInfo.SetValue(instance, double.Parse(value + ""), null);
                        else
                            propertyInfo.SetValue(instance, Enum.Parse(propertyInfo.PropertyType, value + ""), null);
                    }
                    else
                        propertyInfo.SetValue(instance, value, null);
                }
            }
        }

        private static void FillObjectFromDropDownList<T>(T instance, PropertyInfo propertyInfo, object propertyValue)
        {
            if (propertyInfo.PropertyType == typeof(string))
                propertyInfo.SetValue(instance, propertyValue + "", null);

            else if (propertyInfo.PropertyType == typeof(int) || propertyInfo.PropertyType == typeof(int?))
                if (propertyValue != null)
                    propertyInfo.SetValue(instance, int.Parse(propertyValue + ""), null);
                else
                    propertyInfo.SetValue(instance, null, null);

            else if (propertyInfo.PropertyType == typeof(long) || propertyInfo.PropertyType == typeof(long?))
            {
                if (propertyValue != null)
                    propertyInfo.SetValue(instance, long.Parse(propertyValue + ""), null);
                else
                    propertyInfo.SetValue(instance, null, null);
            }
            else if (propertyInfo.PropertyType == typeof(double) || propertyInfo.PropertyType == typeof(double?))
            {
                if (propertyValue != null)
                    propertyInfo.SetValue(instance, double.Parse(propertyValue + ""), null);
                else
                    propertyInfo.SetValue(instance, null, null);
            }
            else
                propertyInfo.SetValue(instance, Enum.Parse(propertyInfo.PropertyType, propertyValue + ""), null);
        }

        private static object GetPropertyValueFromControl(Control control, PropertyInfo propertyInfo)
        {
            if (control is DropDownList)
            {
                string selectedValue = (control as DropDownList).SelectedValue;

                if (selectedValue.ToLower() == "null")
                    selectedValue = null;

                return DBNullHelper.ToType(selectedValue, propertyInfo.PropertyType);
            }
            else if (control is ITextControl)
            {
                string text = (control as ITextControl).Text;

                if (string.IsNullOrWhiteSpace(text) && DBNullHelper.IsNullable(propertyInfo))
                    return null;
                else
                    return DBNullHelper.ToType(text, propertyInfo.PropertyType);
            }
            else if (control is ICheckBoxControl)
            {
                bool isChecked = (control as ICheckBoxControl).Checked;
                return DBNullHelper.ToType(isChecked, propertyInfo.PropertyType);
            }
            else if (control is HiddenField)
            {
                string text = (control as HiddenField).Value;

                if (string.IsNullOrWhiteSpace(text) && DBNullHelper.IsNullable(propertyInfo))
                    return null;
                else
                    return DBNullHelper.ToType(text, propertyInfo.PropertyType);
            }
            else if (control is HyperLink)
            {
                string text = (control as HyperLink).Text;

                if (string.IsNullOrWhiteSpace(text) && DBNullHelper.IsNullable(propertyInfo))
                    return null;
                else
                    return DBNullHelper.ToType(text, propertyInfo.PropertyType);
            }

            return null;
        }

        private static Control LocateControl(Control control, List<Type> controlTypes, string propertyName)
        {
            foreach (Type controlType in controlTypes)
            {
                Control returnControl = LocateControl(control, controlType.Name + "_" + propertyName);

                if (returnControl != null)
                    return returnControl;
            }

            return null;
        }

        private static Control LocateControl(Control control, string controlName)
        {
            Control returnControl = null;

            foreach (Control innerControl in control.Controls)
            {
                if (innerControl.ID != null && innerControl.ID.Equals(controlName, StringComparison.CurrentCultureIgnoreCase) && innerControl is Control)
                    returnControl = innerControl;
                else
                    returnControl = LocateControl(innerControl, controlName);

                if (returnControl != null)
                    break;
            }

            return returnControl;
        }

        private static List<object> ConvertPropertyToObjectList(object propertyValue)
        {
            if (propertyValue == null)
                return new List<object>();

            List<object> objectList = (propertyValue as IEnumerable).Cast<object>().ToList();
            return objectList;
        }
    }
 }
